/*
 *  I2W_Email.cpp
 *
 *  Created by Pat Long (plong0) on 03/03/10.
 *  Copyright 2010 Tangible Interaction Inc. All rights reserved.
 *
 */

#include "I2W_Email.h"

I2W_Email::I2W_Email(){
	this->smtp = NULL;
	this->message = NULL;
	this->setTimeout();
/**	requiredParams.push_back("smtp_server");
	requiredParams.push_back("smtp_port");
	requiredParams.push_back("smtp_username");
	requiredParams.push_back("smtp_password");*/
	
	requiredParams.push_back("sender");
	requiredParams.push_back("recipients");
	requiredParams.push_back("subject");
	requiredParams.push_back("body");
}

I2W_Email::~I2W_Email(){
	if(this->smtp != NULL)
		delete this->smtp;
}

bool I2W_Email::connectSMTP(string smtp_server, int smtpPort, string smtp_username, string smtp_password){
	if(this->smtp != NULL){
		delete this->smtp;
		this->smtp = NULL;
	}
	this->smtp = new ofxSmtpClientUtils(smtp_server, smtpPort, smtp_username, smtp_password, this->timeout);
	return this->smtp->isConnected();
}

void I2W_Email::setTimeout(int timeout){
	this->timeout = timeout;
}

void I2W_Email::update(){
	if(this->message != NULL && this->smtp != NULL && !this->smtp->isThreadRunning()){
		stringstream messageBuilder;
		if(this->message->sent){
			messageBuilder << "I2W_Email: email successfully sent!";
			ofLog(OF_LOG_NOTICE, messageBuilder.str());
			messageBuilder.str("");
			this->setResponseCode(I2W_RESPONSE_SUCCESS);
		}
		else{
			messageBuilder << "I2W_Email: email failed!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			this->setResponseCode(I2W_RESPONSE_RESP_ERROR);
		}
		delete this->message;
		this->message = NULL;
		delete this->smtp;
		this->smtp = NULL;
	}
}

bool I2W_Email::validEmail(string emailAddress){
	if(emailAddress.length() > 0){
		vector<string> emSplit = stringSplit(emailAddress, '@');
		if(emSplit.size() == 2){
			if(emSplit[0].length() > 0 && emSplit[1].length() > 4){
				vector<string> hostSplit = stringSplit(emSplit[1], '.');
				if(hostSplit.size() >= 2){
					int domainLength = hostSplit[hostSplit.size()-1].length();
					if(domainLength >= 2 && domainLength <= 3)
						return true;
				}
			}			
		}
	}
	return false;
}

bool I2W_Email::checkParams(map<string,string> params){
	bool check = Image2WebService::checkParams(params);
	if(check){
		stringstream messageBuilder;
		string checkAddress;
		
		checkAddress = params["sender"];
		if(!validEmail(checkAddress)){
			check = false;
			messageBuilder << "I2W_Email: invalid email address set for 'sender' parameter (" << checkAddress << ")";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
		}
		
		vector<string> recipients = stringSplit(params["recipients"], ',');
		if(recipients.size() > 0){
			for(int i=0; i < recipients.size(); i++){
				checkAddress = recipients[i];
				if(!validEmail(checkAddress)){
					check = false;
					messageBuilder << "I2W_Email: invalid email address set for 'recipients' parameter (" << checkAddress << ")";
					ofLog(OF_LOG_ERROR, messageBuilder.str());
					messageBuilder.str("");
				}
			}
		}		
	}
	return check;
}

bool I2W_Email::postImage(ofxImage image, map<string,string> params){
	stringstream messageBuilder;
	
	if(this->message != NULL){
		messageBuilder << "I2W_Email: already sending a message!";
		ofLog(OF_LOG_ERROR, messageBuilder.str());
		messageBuilder.str("");
		return false;
	}
	
	bool result = false;
	bool goodData = true;
	bool hasNewServer = true;
	
	if(image.getFileName() == ""){
		messageBuilder << "I2W_Email: the image you are trying to send has not been saved to a file!";
		ofLog(OF_LOG_ERROR, messageBuilder.str());
		messageBuilder.str("");
		goodData = false;
	}
		
	if(goodData && this->checkParams(params)){
		int smtpPort = -1;
		vector<string> recipients;

		if(params["smtp_server"] == ""){
			messageBuilder << "I2W_Email: invalid smtp server address given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			hasNewServer = false;
		}
		
		if(!from_string(smtpPort, params["smtp_port"], std::dec)){
			messageBuilder << "I2W_Email: invalid smtp port given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			hasNewServer = false;
		}
		
		if(params["smtp_username"] == ""){
			messageBuilder << "I2W_Email: invalid smtp username given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			hasNewServer = false;
		}
		
		if(params["smtp_password"] == ""){
			messageBuilder << "I2W_Email: invalid smtp password given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			hasNewServer = false;
		}
		
		
		if(params["sender"] == ""){
			messageBuilder << "I2W_Email: invalid sender given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			goodData = false;
		}
		
		if(params["recipients"] == ""){
			messageBuilder << "I2W_Email: invalid recipient given!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			goodData = false;
		}
		else{
			stringSplit(params["recipients"], ',', recipients);
		}
		
		if(!hasNewServer && (this->smtp == NULL || !this->smtp->isConnected())){
			messageBuilder << "I2W_Email: no parameters provided for SMTP server connection!";
			ofLog(OF_LOG_ERROR, messageBuilder.str());
			messageBuilder.str("");
			goodData = false;
		}
		
		if(goodData){
			if(this->smtp == NULL || !this->smtp->isConnected() || hasNewServer)
				this->connectSMTP(params["smtp_server"], smtpPort, params["smtp_username"], params["smtp_password"]);

			if(this->smtp != NULL && this->smtp->isConnected()){
				this->message = new ofxMailMessage();
				for(int i=0; i < recipients.size(); i++)
					this->message->recipients.push_back(recipients[i]);
				this->message->sender = params["sender"];
				this->message->subject = params["subject"];
				this->message->content = params["body"];
				this->message->date=Poco::Timestamp();
				this->message->attachmentPaths.push_back(image.getFileName());
				this->setResponseCode(I2W_RESPONSE_WAITING);
				this->smtp->addMessage(this->message);
				
				messageBuilder << "I2W_Email: sending email";
				ofLog(OF_LOG_NOTICE, messageBuilder.str());
				messageBuilder.str("");
				result = true;
			}
			else{
				this->setResponseCode(I2W_RESPONSE_RESP_ERROR);
			}
		}
	}
	
	if(!goodData){
		this->setResponseCode(I2W_RESPONSE_SEND_ERROR);
	}
	
	return result;
}
